package com.joyance.springmvc.util;

import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class RSAUtils {

    private static String RSA = "RSA";

    private byte[] rsa_public_key;

    private byte[] rsa_private_key;

    private static String MD5WITHRSA = "MD5withRSA";


    public RSAUtils() throws NoSuchAlgorithmException {
        generateRSAKey();
    }


    public void generateRSAKey() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        rsa_private_key = keyPair.getPrivate().getEncoded();
        rsa_public_key = keyPair.getPublic().getEncoded();
    }


    public String encryptByPrivateKey(String data) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PKCS8EncodedKeySpec pkcS8EncodedKeySpec = new PKCS8EncodedKeySpec(rsa_private_key);
        PrivateKey key = keyFactory.generatePrivate(pkcS8EncodedKeySpec);
        Cipher cipher = Cipher.getInstance(RSA);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return encoderBase64(cipher.doFinal(data.getBytes()));
    }


    public String decryptByPublicKey(String data) throws Exception {
        byte[] byte_data = decoderBase64(data);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsa_public_key);
        PublicKey key = keyFactory.generatePublic(x509EncodedKeySpec);
        Cipher cipher = Cipher.getInstance(RSA);
        cipher.init(Cipher.DECRYPT_MODE, key);
        return new String(cipher.doFinal(byte_data));
    }


    public String sign(String data, String private_key) throws Exception {
        PKCS8EncodedKeySpec pkcS8EncodedKeySpec = new PKCS8EncodedKeySpec(decoderBase64(private_key));
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcS8EncodedKeySpec);
        Signature signature = Signature.getInstance(MD5WITHRSA);
        signature.initSign(privateKey);
        signature.update(data.getBytes());
        return encoderBase64(signature.sign());
    }


    public boolean isVerify(String sign, String data, String public_key) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decoderBase64(public_key));
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        Signature signature = Signature.getInstance(MD5WITHRSA);
        signature.initVerify(publicKey);
        signature.update(data.getBytes());
        return signature.verify(decoderBase64(sign));
    }


    public String encoderBase64(byte[] data) {
        return new BASE64Encoder().encode(data);
    }


    public byte[] decoderBase64(String data) throws IOException {
        return new BASE64Decoder().decodeBuffer(data);
    }



    public String getRsa_public_key() {
        return encoderBase64(rsa_public_key);
    }



    public String getRsa_private_key() {
        return encoderBase64(rsa_private_key);
    }


    public static void main(String[] args) {
        try {
            RSAUtils util = new RSAUtils();
            String private_key = util.getRsa_private_key();
            String public_key = util.getRsa_public_key();

            // String encrypt_data = util.encryptByPrivateKey("name=joyance");
            // System.out.println(encrypt_data);
            // System.out.println();
            // System.out.println(util.decryptByPublicKey(encrypt_data));
            // System.out.println("private_key=" + private_key + "+++++++++++++++++++public_key=" + public_key);
            // String sign = util.sign("name=joyance", private_key);
            // System.out.println("sign=" + sign);
            // boolean isVerify = util.isVerify(sign, "name=joyance", public_key);
            // System.out.println("isVerify=" + isVerify);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}
